package com.hncc.kumao.tool;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.struts2.components.Else;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hncc.kumao.entity.BreakpointUploadTask;
import com.hncc.kumao.entity.NetdiskAccessToken;
import com.hncc.kumao.entity.OfflineDownloadTask;
import com.hncc.kumao.exception.KumaoException;
import com.hncc.kumao.exception.KumaoNetdiskFileNotFoundException;
import com.hncc.kumao.util.ConstValue;
import com.hncc.kumao.util.EncodeUtils;
import com.hncc.kumao.util.MyDownloadProgress;
import com.hncc.kumao.util.MyHttpClientUtils;
import com.hncc.kumao.util.OfflineDownloadUtils;

public class BaiDuOperation {

    private static String taskId;

    /**
     * 检查当前网盘信息是否有效
     * @param netdiskAccessToken 网盘信息
     * @return
     */
    public static boolean check(NetdiskAccessToken netdiskAccessToken) {
        String checkUrl = "https://pan.baidu.com/rest/2.0/xpan/nas?method=uinfo&access_token=" + netdiskAccessToken.getAccessToken();
        String responseContent = "";
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        try {  
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(10000)
                    .setConnectionRequestTimeout(10000)
                    .setSocketTimeout(10000)
                    .build();
            HttpGet httpGet = new HttpGet(checkUrl);
            httpGet.setConfig(requestConfig);
            response = httpclient.execute(httpGet);
            //System.out.println(response.getStatusLine());
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();  
            responseContent = MyHttpClientUtils.getResponseString(entity);
            //System.out.println("debug:" + responseContent);  
            EntityUtils.consume(entity);
            if(statusCode == 200) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {  
            e.printStackTrace();
            return false;
        } finally {  
            try {
                if(response != null) {
                    response.close();
                }
                httpclient.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }
    
    // 进行下载
    public static void download(OfflineDownloadTask offlineDownloadTask, NetdiskAccessToken netdiskAccessToken,
            final MyDownloadProgress progress) throws Exception {
        try {
            taskId = offlineDownloadTask.getId();
            String fileUri = offlineDownloadTask.getFileUri();
            // 获取fsid和token
            BigInteger fsid = JSON.parseObject(offlineDownloadTask.getFileInfoString()).getBigInteger("fsid");
            String accessToken = netdiskAccessToken.getAccessToken();
            // 获取下载连接
            String getDownloadUrl = "https://pan.baidu.com/rest/2.0/xpan/multimedia?method=filemetas&access_token=" 
                    + accessToken + "&fsids=[" + fsid + "]&dlink=1";
            String downloadUrl = getDownloadUrl(getDownloadUrl);
            downloadUrl += "&access_token=" + accessToken;
            System.out.println("下载链接" + downloadUrl);
            // 执行下载
            doDownload(downloadUrl, offlineDownloadTask.getFileSavePath(), new MyDownloadProgress() {
                @Override
                public void onProgress(Long currentSize, Long totalSize) {
                    System.out.println(currentSize + "/" + totalSize);
                    progress.onProgress(currentSize, totalSize);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    // 获取下载链接
    private static String getDownloadUrl(String url) throws Exception {
        String responseContent = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String downloadUrl = null;
        try {
            // 获取dlink
            HttpGet httpGet = new HttpGet(url);
            response = httpclient.execute(httpGet);
            //System.out.println(response.getStatusLine());
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            responseContent = MyHttpClientUtils.getResponseString(entity);
            //System.out.println("debug:" + responseContent);
            EntityUtils.consume(entity);
            JSONObject jsonObject = JSON.parseObject(responseContent);
            if(jsonObject.getJSONArray("list").size() <= 0) {
                System.out.println("未找到该文件");
                throw new KumaoNetdiskFileNotFoundException("未找到该文件");
            }
            downloadUrl = jsonObject.getJSONArray("list").getJSONObject(0).getString("dlink");
            // System.out.println("纯dlink: " + downloadUrl);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return downloadUrl;
    }

    // 具体执行下载的方法
    private static void doDownload(String downloadUrl, String fileSavePath, MyDownloadProgress progress)
            throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            HttpGet httpGet = new HttpGet(downloadUrl);
            response = httpclient.execute(httpGet);
            System.out.println(response.getStatusLine());
            HttpEntity httpEntity = response.getEntity();
            long contentLength = httpEntity.getContentLength();
            // 获取输入流
            is = httpEntity.getContent();
            // 创建文件输出流
            if (OfflineDownloadUtils.getTaskProgressState(taskId) == ConstValue.OD_TASK_STATE_GOING) {
                // 先创建文件夹，防止文件夹不存在报错
                File tempFile = new File(fileSavePath);
                if (!tempFile.exists()) {
                    if (!tempFile.getParentFile().exists()) {
                        tempFile.getParentFile().mkdirs();
                    }
                }
                fos = new FileOutputStream(fileSavePath);
            }
            byte[] buffer = new byte[4096];
            int r = 0;
            long totalRead = 0;
            if (fos != null) {
                while (((r = is.read(buffer)) > 0)) {
                    if (OfflineDownloadUtils.getTaskProgressState(taskId) != ConstValue.OD_TASK_STATE_GOING) {
                        break;
                    }
                    fos.write(buffer, 0, r);
                    totalRead += r;
                    if (progress != null) {
                        progress.onProgress(totalRead, contentLength);
                    }
                }
            }
            EntityUtils.consume(httpEntity);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (is != null) {
                is.close();
            }
            if (fos != null) {
                fos.close();
            }
            if (response != null) {
                response.close();
            }
            if (httpclient != null) {
                httpclient.close();
            }
        }
    }

    //上传文件
    public static void upload(BreakpointUploadTask breakpointUploadTask, NetdiskAccessToken netdiskAccessToken) throws Exception {
        try {
            String uploadUrl = "https://c.pcs.baidu.com/rest/2.0/pcs/file?method=upload&access_token=" + 
                    netdiskAccessToken.getAccessToken() + "&path=/apps/BTBD" + breakpointUploadTask.getFileUri();
            //进行上传
            CloseableHttpClient httpclient = null;
            CloseableHttpResponse response = null;
            try {
                httpclient = HttpClients.createDefault();  
                HttpPost httpPost = new HttpPost(uploadUrl);
                httpPost.addHeader("User-Agent", "pan.baidu.com");
                httpPost.addHeader("Accept-Encoding", "*");
                MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();  
                //设置文件部分
                File uploadFile = new File(breakpointUploadTask.getFileServerPath());
                FileBody fileBody = new FileBody(uploadFile);  
                //添加进去
                multipartEntityBuilder.addPart("file", fileBody);
                
                HttpEntity requesEntity = multipartEntityBuilder.build();
                httpPost.setEntity(requesEntity);
                response = httpclient.execute(httpPost);
                System.out.println(response.getStatusLine());
                int statusCode = response.getStatusLine().getStatusCode();
                HttpEntity responseEntity = response.getEntity();
                String responseContent = MyHttpClientUtils.getResponseString(responseEntity);
                System.out.println("上传返回的信息: " + responseContent);
                EntityUtils.consume(responseEntity);
                Integer errorCode = JSON.parseObject(responseContent).getInteger("error_code");
                if(statusCode == 200) {
                    //移动文件到真正显示的目录
                    String moveUrl = "https://pan.baidu.com/rest/2.0/xpan/file?method=filemanager&opera=move&ondup=newcopy&access_token=" + 
                            netdiskAccessToken.getAccessToken();
                    httpPost = new HttpPost(moveUrl);
                    
                    //设置头
                    httpPost.addHeader("content-type", "application/x-www-form-urlencoded");
                    httpPost.addHeader("User-Agent", "pan.baidu.com");
                    httpPost.addHeader("Accept-Encoding", "*");
                    
                    //要保存的目录路径
                    String fileUri = breakpointUploadTask.getFileUri();
                    String targetDir = fileUri.substring(0, fileUri.lastIndexOf("/"));
                    //要移动的文件路径
                    String filePath = "/apps/BTBD" + fileUri;
                    Map dataMap = new HashMap();
                    dataMap.put("path", filePath);
                    dataMap.put("dest", targetDir);
                    String dataString = JSON.toJSONString(dataMap);
                    //拼接参数
                    BasicNameValuePair pair1 = new BasicNameValuePair("asycn", "1");
                    BasicNameValuePair pair2 = new BasicNameValuePair("filelist", "[" + dataString + "]");
                    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                    nvps.add(pair1);
                    nvps.add(pair2);
                    UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvps, "UTF-8");
                    
                    //设置请求参数
                    httpPost.setEntity(urlEncodedFormEntity);
                    
                    //进行请求
                    response = httpclient.execute(httpPost);
                    System.out.println(response.getStatusLine());
                    statusCode = response.getStatusLine().getStatusCode();
                    responseEntity = response.getEntity();
                    responseContent = MyHttpClientUtils.getResponseString(responseEntity);
                    System.out.println("上传返回的信息: " + responseContent);
                    EntityUtils.consume(responseEntity);
                } else if(errorCode == 31061) {
                    throw new KumaoException("该文件已存在");
                } else {
                    throw new KumaoException("上传文件失败");
                }
            } catch (Exception e) {
                //e.printStackTrace();
                throw e;
            } finally {
                if(response != null) {
                    response.close();
                }
                if(httpclient != null) {
                    httpclient.close();
                }
            }
        } catch (Exception e) {
            //e.printStackTrace();
            throw e;
        }
    }
}
